iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0
DevOps

30 天挑戰 CKAD 認證!菜鳥的 Kubernetes 學習日記系列 第 25

【Day25】Kustomize:不用模板也能客製化 Kubernetes 配置 - Part1

  • 分享至 

  • xImage
  •  

gh

前情提要

昨天我們深入了解了 Helm 這個 Kubernetes 的套件管理器。從實戰中體驗到 Repository 生態系統可以直接拉取別人打包好的 Chart,雖然沒用自己實作打包成 Helm Chart,但是大方向的概念是一樣的。透過模板化和 values.yaml 解決了多環境配置管理的難題。我們成功部署了 WordPress,見證了原本需要多個 YAML 檔案的複雜應用,現在只需要一個 helm install 指令就能完成。

然而,Helm 的 Go Template 語法有一定的學習門檻,而且在某些場景下,我們可能只是需要對現有的 YAML 檔案進行小幅調整,而不需要完整的模板化功能。今天要看到的 Kustomize 正是為了這類需求而生。它採用完全不同的思路,透過「疊加」(Overlay)和「修補」(Patch)的方式來管理配置,而且已經被整合進 kubectl 成為 Kubernetes 的原生功能。

為什麼需要 Kustomize?

讓我們從一個實際的痛點開始。假設我們有一個 nginx deployment,需要在 Dev、Stage、Prod 三個環境中部署。開發環境在本地機器只需要 1 個副本,測試環境需要 2-3 個,生產環境則需要 5-10 個來處理大量流量。

最直覺的解決方案是為每個環境建立獨立的目錄,將 YAML 檔案複製三份,然後分別修改 replicas 的值。這看起來沒什麼問題,但當應用程式成長,需要管理的資源從一個 deployment 變成數十個檔案時,問題就來了。每次要新增 Service 或 ConfigMap,都要記得複製到所有環境的目錄;每次要修改配置,都要在三個地方同步更新。遲早會有人忘記同步某個檔案,造成環境間的配置不一致。

這種重複性的配置管理不僅容易出錯,也違反了程式設計的 DRY(Don't Repeat Yourself) 原則。因此用一種方法來重複使用 Kubernetes 配置,只修改需要改變的部分,而不是複製整份配置。

Kustomize 的解決方案

Kustomize 引入了兩個核心概念來解決這個問題:BaseOverlays

Base 代表所有環境共用的基礎配置。這些是不會因環境而改變的資源定義,或是可以作為預設值的配置。比如說,你的 nginx deployment 的基本結構、使用的映像檔、健康檢查設定等,在所有環境都是一樣的,這些就放在 Base 中。

Overlays 則是針對特定環境的客製化配置。每個環境都有自己的 Overlay,用來覆蓋或修改 Base 中的特定值。Dev 環境的 Overlay 可能不需要任何修改(如果 Base 的預設值剛好符合),Stage 環境的 Overlay 將 replicas 改為 2,Prod 環境的 Overlay 則改為 5。

Kustomize 的工作流程很簡單:它會將 Base 配置和特定環境的 Overlay 結合,產生最終的 Kubernetes manifest。整個過程不需要任何模板語法,所有檔案都是標準的 YAML,可以直接被 Kubernetes 和其他工具讀取、驗證。

Kustomize vs Helm

在深入 Kustomize 之前,讓我們快速和昨天剛看完的 Helm 比較一下他們的差異。

Helm 使用 Go Template 語法來處理變數。我們會在 YAML 中看到 {{ .Values.replicaCount }} 這樣的模板語法,然後在 values.yaml 中定義實際的值。這種方式功能強大,支援條件判斷、迴圈、函式等進階功能,但也讓 YAML 檔案變得不再是純粹的 YAML,有時候會變得難以閱讀。

Kustomize 則保持簡單。它不使用任何模板語法,所有檔案都是標準的 YAML。我們直接編寫完整的 Kubernetes 資源定義,然後透過 Overlay 和 Patch 來修改特定的值。這種方式雖然功能較少,但學習門檻低,而且所有檔案都可以直接被 Kubernetes 工具處理。

選擇 Helm 還是 Kustomize,取決於實際專案的需求。如果是需要完整的套件管理功能、複雜的邏輯處理,Helm 是更好的選擇。但如果只是需要管理多環境配置,希望保持簡單直觀,Kustomize 可能會是更合適的選擇。

kustomization.yaml:配置的中心

Kustomize 的核心是 kustomization.yaml 檔案。這個檔案必須準確命名(不能是 kustomization.yml 或其他變體),Kustomize 會在指定目錄中尋找這個檔案。

kustomization.yaml 包含兩個主要部分:

第一部分是 resources,列出所有要被 Kustomize 管理的 Kubernetes 資源檔案。這就像是告訴 Kustomize:「這些是我要部署的東西」。

第二部分是 transformations(轉換),定義要對這些資源進行的修改。比如添加共同的標籤、修改名稱前綴、調整資源限制等。

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - nginx-deployment.yaml
  - nginx-service.yaml

commonLabels:
  company: IThome

這個簡單的例子展示了 Kustomize 的基本結構。它會載入兩個資源檔案,然後為所有資源添加一個 company: IThome 的標籤。

管理多目錄結構

隨著應用程式成長,我們可能會將不同的元件組織到不同的目錄中。比如 API 相關的配置放在 api/ 目錄,資料庫配置放在 database/ 目錄,快取配置放在 cache/ 目錄。

傳統上,我們需要進入每個目錄分別執行 kubectl apply,或是使用多個 -f 參數。但 Kustomize 提供了更方便的解決方案。

我們可以在根目錄建立一個 kustomization.yaml,列出所有子目錄的資源。但更好的做法是在每個子目錄也建立自己的 kustomization.yaml,管理該目錄內的資源,然後在根目錄的 kustomization.yaml 中引用這些子目錄:

# 根目錄的 kustomization.yaml
resources:
  - api
  - database
  - cache
    
# 子目錄 db/kustomization.yaml (子目錄結構都會類似)
resources:
  - db-depl.yaml
  - db-svc.yaml

當 Kustomize 看到資源指向一個目錄而非檔案時,它會進入該目錄尋找 kustomization.yaml,並遞迴地處理所有資源。這種階層式的組織方式讓大型專案的配置管理變得更有條理。

Kustomize 的輸出與應用

執行 kustomize build 指令時,Kustomize 會處理所有資源和轉換,然後將最終的 YAML 輸出到終端。注意,這個指令只是顯示結果,並不會實際部署到 Kubernetes。

要實際部署,你需要將輸出導向 kubectl apply

kustomize build k8s | kubectl apply -f -

或者使用 kubectl 的內建支援(注意是 -k 而非 -f):

kubectl apply -k k8s

這兩個指令效果相同,都會將 Kustomize 處理後的配置部署到 Kubernetes。刪除資源時,只要將 apply 改為 delete 即可。

實戰 🔥

假設我目前有一個專案,包含了資料庫、訊息佇列和網頁伺服器等多個 Components,結構如下圖。總共有八個不同的資源檔案分散在三個 subdirectories 中。如果按照傳統方式,我們需要進入每個目錄分別執行 kubectl apply,或是用多個 -f 參數一次指定所有檔案,這不僅麻煩,也容易遺漏。

gh

方法一:直接列出所有資源

首先,我們在根目錄建立 kustomization.yaml,將所有資源檔案的路徑都列出來:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - db/db-config.yaml
  - db/db-depl.yaml
  - db/db-service.yaml
  - message-broker/rabbitmq-config.yaml
  - message-broker/rabbitmq-depl.yaml
  - message-broker/rabbitmq-service.yaml
  - nginx/nginx-depl.yaml
  - nginx/nginx-service.yaml

現在只需要一個指令就能將所有服務啟動:

kubectl apply -k k8s/

gh

可以看到所有資源都被成功建立:

gh

方法二:階層式管理

雖然上面的方法可行,但當資源檔案越來越多時,根目錄的 kustomization.yaml 會變得太多難以維護。更好的做法是採用階層式管理:在每個 subdirectories 建立自己的 kustomization.yaml,然後在根目錄引用這些 subdirectories。

# 根目錄的 kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - db/
  - message-broker/
  - nginx/

每個子目錄都有自己的 kustomization.yaml

# db/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - db-config.yaml
  - db-depl.yaml
  - db-service.yaml

# message-broker/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - rabbitmq-config.yaml
  - rabbitmq-depl.yaml
  - rabbitmq-service.yaml

# nginx/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - nginx-depl.yaml
  - nginx-service.yaml

這種結構化的方式讓每個元件的配置都保持在自己的目錄中,維護起來更加清晰:

gh

執行結果與方法一相同,所有資源都成功部署:

gh

階層式管理的好處是當專案規模擴大時,你可以輕鬆地新增或移除整個元件,只需要在根目錄的 kustomization.yaml 中調整子目錄列表即可,不需要逐一管理個別檔案。

總結

今天我們學習了 Kustomize 的基礎概念和實際應用。從理解為什麼需要 Kustomize 開始,我們看到了它如何用 Base 和 Overlays 的概念優雅地解決多環境配置管理的問題,不需要複製大量的 YAML 檔案,也不需要學習複雜的模板語法。

透過實戰,我們掌握了 kustomization.yaml 的基本結構,學會了如何管理分散在多個目錄中的資源檔案。特別是階層式的組織方式,讓大型專案的配置管理變得更有條理。相較於 Helm 的模板化方式,Kustomize 保持了所有檔案都是標準 YAML 的簡潔性,這讓配置更容易理解和除錯。

然而,今天我們只接觸了 Kustomize 的基礎。真正讓 Kustomize 強大的是它的 TransformersPatches 功能。明天我們將深入探討如何使用 Common Transformers 來統一修改資源屬性、用 Image Transformers 管理不同環境的映像檔版本、透過 Strategic Merge Patch 和 JSON Patch 精確地修改配置,以及如何使用 Overlays 和 Components 建立可重複使用的配置片段。

下一篇文章:Kustomize:不用模板也能客製化 Kubernetes 配置 - Part2


上一篇
【Day24】Kubernetes 的套件管理器:Helm 與 Chart 實戰
下一篇
【Day26】Kustomize:不用模板也能客製化 Kubernetes 配置 - Part2
系列文
30 天挑戰 CKAD 認證!菜鳥的 Kubernetes 學習日記26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言